package com.googlecode.vmock.matchers;

import java.util.Arrays;

import com.googlecode.vmock.matchers.ranking.MatcherRanking;
import com.googlecode.vmock.utils.ObjectUtils;

/**
 * A Matcher that matches against all objects that are equal to a given object.
 * <p>
 * This matcher is null-safe.
 * 
 * @author marcin.jagus
 */
public class EqualsMatcher extends AbstractMatcher {

    static {
        MatcherRanking.setRanking(EqualsMatcher.class, MatcherRanking.EQUALS_MATCHER_DEFAULT_RANKING);
    }

    /**
     * Accepted value.
     */
    private Object value;

    /**
     * Creates a new matcher for a given value.
     * 
     * @param value Given value. Can be <code>null</code>.
     */
    public EqualsMatcher(Object value) {
        this.value = value;
    }

    /**
     * Returns <code>true</code> if a given value is equal to the accepted value.
     * <p>
     * If both given and accepted values are arrays, their contents are compare in order to dermine if they are equal.
     */
    @Override
    public boolean matches(Object value) {
        if (isArray(this.value) && isArray(value)) {
            return Arrays.equals((Object[]) this.value, (Object[]) value);
        } else {
            return ObjectUtils.equals(this.value, value);
        }
    }

    /**
     * Checks if a given value is an array.
     * 
     * @param value given value
     * @return <code>true</code> if a given value is non-null and is an array.
     */
    private boolean isArray(Object value) {
        return value != null && value.getClass().isArray();
    }

    @Override
    public String toString() {
        return String.format("EqualsMatcher(%s)", value);
    }
}
